package com.wfs.myapp.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.wfs.myapp.common.ApiResult;
import com.wfs.myapp.entity.domain.User;
import com.wfs.myapp.entity.domain.bk.*;
import com.wfs.myapp.entity.domain.dota.DotaEquip;
import com.wfs.myapp.enums.ResponseCodeEnum;
import com.wfs.myapp.enums.SearchTypeEnum;
import com.wfs.myapp.remote.wx.WxRemoteService;
import com.wfs.myapp.repository.UserRepository;
import com.wfs.myapp.repository.bk.*;
import com.wfs.myapp.repository.dota.DotaEquipRepository;
import com.wfs.myapp.utils.SqeUtil;
import io.swagger.annotations.Api;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.*;

@RestController
@RequestMapping("/file")
@Api(value = "上传", tags = "上传")
@Slf4j
public class UpLoadController {

    @Value("${app.file.type}")
    private String IMAGE_FILE;

    @Value("${base.url}")
    private String baseUrl;

    @Value("${talk-record.result}")
    private String resultPath;

    @Value("${app.files.path}")
    private String filesPath;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private BookRepository bookRepository;

    @Autowired
    private GroupRepository groupRepository;

    @Autowired
    private FeedBackRepository feedBackRepository;

    @Autowired
    private TalkRecordRepository talkRecordRepository;
    @Autowired
    private DishRepository dishRepository;

    @Autowired
    private WxRemoteService remoteService;

    @Autowired
    private DotaEquipRepository dotaEquipRepository;

    @PostMapping("/upload")
    public ApiResult upload(@RequestParam("file") MultipartFile file, @RequestParam("type") Integer type, @RequestParam("param") String param) throws IOException {
        String reqFileName = file.getOriginalFilename();
        String fileType = reqFileName.substring(reqFileName.indexOf(".")+1);
        if (!Arrays.asList(IMAGE_FILE.split(",")).contains(fileType)) return ApiResult.error("不是图片类型");
        if (type.equals(SearchTypeEnum.USER.getCode())) {
            // 用户头像
            User user = JSONObject.parseObject(param, User.class);
            String fileName = "user_avatar_" + user.getId() + reqFileName;
            Optional<User> byId = userRepository.findById(user.getId());
            if (!byId.isPresent()) return ApiResult.error(ResponseCodeEnum.USER_NOT_EXIST);
            File saveFile = new File(filesPath + SearchTypeEnum.USER.getPath() + File.separator + fileName);
            if (Files.exists(Paths.get(saveFile.getPath()))) saveFile.delete();
            try {
                file.transferTo(saveFile);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            return ApiResult.success(baseUrl + "/file/image" + SearchTypeEnum.USER.getPath() + "?imageName=" + fileName);
        } else if (type.equals(SearchTypeEnum.BOOK.getCode())) {
            // 书籍图片
            BkBook book = JSONObject.parseObject(param, BkBook.class);
            String fileName = "book_avatar_" + book.getId() + reqFileName;
            Optional<BkBook> byId = bookRepository.findById(book.getId());
            if (!byId.isPresent()) return ApiResult.error(ResponseCodeEnum.BOOK_NOT_EXIST);
            BkBook book1 = byId.get();
            String bookAvatar = baseUrl + "/file/image" + SearchTypeEnum.BOOK.getPath() + "?imageName=" + fileName;
            book1.setBookAvatar(bookAvatar);
            bookRepository.save(book1);
            File saveFile = new File(filesPath + SearchTypeEnum.BOOK.getPath() + File.separator + fileName);
            if (Files.exists(Paths.get(saveFile.getPath()))) saveFile.delete();
            try {
                file.transferTo(saveFile);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            return ApiResult.success(bookAvatar);
        } else if (type.equals(SearchTypeEnum.GROUP.getCode())) {
            // 组头像
            BkGroup group = JSONObject.parseObject(param, BkGroup.class);
            String fileName = "group_avatar_" + group.getId() + reqFileName;
            Optional<BkGroup> byId = groupRepository.findById(group.getId());
            if (!byId.isPresent()) return ApiResult.error(ResponseCodeEnum.BOOK_NOT_EXIST);
            BkGroup group1 = byId.get();
            String bookAvatar = baseUrl + "/file/image" + SearchTypeEnum.GROUP.getPath() + "?imageName=" + fileName;
            group1.setGroupAvatar(bookAvatar);
            groupRepository.save(group1);
            File saveFile = new File(filesPath + SearchTypeEnum.GROUP.getPath() + File.separator + fileName);
            if (Files.exists(Paths.get(saveFile.getPath()))) saveFile.delete();
            try {
                file.transferTo(saveFile);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            return ApiResult.success(bookAvatar);
        } else if (type.equals(SearchTypeEnum.FEEDBACK.getCode())) {
            // 意见反馈
            BkFeedback feedbackReq = JSONObject.parseObject(param, BkFeedback.class);
            String fileName = "feedback_image_" + feedbackReq.getId() + "_" + reqFileName;
            Optional<BkFeedback> byId = feedBackRepository.findById(feedbackReq.getId());
            if (!byId.isPresent()) return ApiResult.error(ResponseCodeEnum.BOOK_NOT_EXIST);
            BkFeedback feedback = byId.get();
            String feedbackFilesPath = feedback.getFiles();
            List<String> strings = StringUtils.isNotBlank(feedbackFilesPath) ? JSONArray.parseArray(feedbackFilesPath, String.class) : new ArrayList<>();
            strings.add(fileName);
            feedback.setFiles(JSONArray.toJSONString(strings));
            feedBackRepository.save(feedback);
            File saveFile = new File(filesPath + SearchTypeEnum.FEEDBACK.getPath() + File.separator + fileName);
            if (Files.exists(Paths.get(saveFile.getPath()))) saveFile.delete();
            try {
                file.transferTo(saveFile);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            return ApiResult.success(fileName);
        } else if (type.equals(SearchTypeEnum.TALK_RECORD.getCode())) {
            // 存图片
            BkTalkRecord reqDto = JSONObject.parseObject(param, BkTalkRecord.class);
            log.info("reqDto:{}", reqDto);
            String fileName = reqDto.getUserId() + "_" + SqeUtil.getOrderSeq("talk_record_image_");
            BkTalkRecord bkTalkRecord = null;
            File path = new File(resultPath);
            if (!path.exists()) path.mkdir();
            if (Objects.isNull(reqDto.getId())) {
                // 第一次对方头像上传
                bkTalkRecord = new BkTalkRecord();
                bkTalkRecord.setUserId(reqDto.getUserId());
                bkTalkRecord.setMyContent(reqDto.getMyContent());

                bkTalkRecord.setOtherContent(reqDto.getOtherContent());
                bkTalkRecord.setOtherName(reqDto.getOtherName());
                bkTalkRecord.setCreatedBy(String.valueOf(reqDto.getUserId()));
                bkTalkRecord.setUpdatedBy(String.valueOf(reqDto.getUserId()));

                // 头像地址
                String otherAvatarPath = resultPath + fileName;
                bkTalkRecord.setOtherAvatar(otherAvatarPath);
                bkTalkRecord = talkRecordRepository.save(bkTalkRecord);
            } else {
                // 第二次我的头像上传 带id
                Optional<BkTalkRecord> byId = talkRecordRepository.findById(reqDto.getId());
                if (byId.isPresent()) {
                    bkTalkRecord = byId.get();
                    // 头像地址
                    String myAvatarPath = resultPath + fileName;
                    bkTalkRecord.setMyAvatar(myAvatarPath);
                    talkRecordRepository.save(bkTalkRecord);
                }
            }
            log.info("globalPath:{}", resultPath + fileName);
            File saveFile = new File(resultPath + fileName);
            if (Files.exists(Paths.get(saveFile.getPath()))) saveFile.delete();
            try {
                file.transferTo(saveFile);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            return ApiResult.success(bkTalkRecord);
        } else if (type.equals(SearchTypeEnum.DISH_RECORD.getCode())) {
            // 菜品图片
            BkDish dish = JSONObject.parseObject(param, BkDish.class);
            String fileName = "dish_avatar_" + dish.getId() + reqFileName;
            Optional<BkDish> byId = dishRepository.findById(dish.getId());
            if (!byId.isPresent()) return ApiResult.error(ResponseCodeEnum.DISH_NOT_EXIST);
            BkDish dish1 = byId.get();
            String bookAvatar = baseUrl + "/file/image/dish?imageName=" + fileName;
            dish1.setAvatar(bookAvatar);
            dishRepository.save(dish1);
            File saveFile = new File(filesPath + SearchTypeEnum.DISH_RECORD.getPath() + File.separator + fileName);
            if (Files.exists(Paths.get(saveFile.getPath()))) saveFile.delete();
            try {
                file.transferTo(saveFile);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            return ApiResult.success(bookAvatar);
        }
        return ApiResult.success("失败");
    }


    @GetMapping("/download")
    public void download(@RequestParam("type") Integer type, @RequestParam("param") String param, HttpServletResponse response) throws UnsupportedEncodingException {
        // 清空缓冲区，状态码和响应头(headers)
        response.reset();
        // 设置ContentType，响应内容为二进制数据流，编码为utf-8，此处设定的编码是文件内容的编码
        response.setContentType("image/png;charset=utf-8");
        String fileName = "";
        File file = null;
        byte[] buffer = new byte[8192];
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        ByteArrayInputStream byteArrayInputStream = null;
        if (type.equals(SearchTypeEnum.USER.getCode())) {
            Optional<User> byId = userRepository.findById(Long.valueOf(param));
            if (byId.isPresent()) {
                User user = byId.get();
                fileName = user.getAvatar().split("=")[1];  // http://localhost:8091/file/image/user?imageName=user_avatar_8.png
                file = new File(filesPath + SearchTypeEnum.USER.getPath() + File.separator + fileName);
            }
        } else if (type.equals(SearchTypeEnum.BOOK.getCode())) {
            Optional<BkBook> byId = bookRepository.findById(Long.valueOf(param));
            if (byId.isPresent()) {
                BkBook book = byId.get();
                fileName = book.getBookAvatar().split("=")[1];  // http://localhost:8091/file/image/book?imageName=book_avatar_8.png
                file = new File(filesPath + SearchTypeEnum.BOOK.getPath() + File.separator + fileName);
            }
        } else if (type.equals(SearchTypeEnum.GROUP.getCode())) {
            Optional<BkGroup> byId = groupRepository.findById(Long.valueOf(param));
            if (byId.isPresent()) {
                BkGroup group = byId.get();
                fileName = group.getGroupAvatar().split("=")[1];  // http://localhost:8091/file/image/book?imageName=book_avatar_8.png
                file = new File(filesPath + SearchTypeEnum.GROUP.getPath() + File.separator + fileName);
            }
        } else if (type.equals(SearchTypeEnum.GROUP_SHARE.getCode())) {
            JSONObject jsonObject = JSONObject.parseObject(param);
            String pagePath = jsonObject.getString("pagePath");
            String scene = jsonObject.getString("scene");
            // 获取字节流
            try {
                OutputStream os = response.getOutputStream();
                byte[] qrCode = remoteService.getQrCode(pagePath, scene);
                byteArrayInputStream = new ByteArrayInputStream(qrCode);
                int i = byteArrayInputStream.read(buffer);
                while (i != -1) {
                    os.write(buffer, 0, i);
                    i = byteArrayInputStream.read(buffer);
                }
                return;
            } catch (IOException e) {
                // 专门处理Broken pipe异常
                if (e.getMessage().contains("Broken pipe")) {
                    log.warn("客户端已断开连接，终止文件下载: {}", fileName);
                } else {
                    log.error("文件下载失败: {}", fileName, e);
                }
            } finally {
                if (byteArrayInputStream != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        } else if (type.equals(SearchTypeEnum.DISH_RECORD.getCode())) {
            Optional<BkDish> byId = dishRepository.findById(Long.valueOf(param));
            if (byId.isPresent()) {
                BkDish dish = byId.get();
                fileName = dish.getAvatar().split("=")[1];  // http://localhost:8091/file/image/dish?imageName=book_avatar_8.png
                file = new File(filesPath + SearchTypeEnum.DISH_RECORD.getPath() + File.separator + fileName);
            }
        } else if (type.equals(SearchTypeEnum.DOTA_EQUIP.getCode())) {
            Optional<DotaEquip> byId = dotaEquipRepository.findById(Long.valueOf(param));
            if (byId.isPresent()) {
                DotaEquip equip = byId.get();
                fileName = equip.getAvatar().split("=")[1];  // http://localhost:8091/file/image/dota/equip?imageName=治疗指环.png
                file = new File(filesPath + SearchTypeEnum.DOTA_EQUIP.getPath() + File.separator + fileName);
            }
        }
        // 实现文件下载
        try {
            fis = new FileInputStream(file);
            bis = new BufferedInputStream(fis);
            // 获取字节流
            OutputStream os = response.getOutputStream();
            int i = bis.read(buffer);
            while (i != -1) {
                os.write(buffer, 0, i);
                i = bis.read(buffer);
            }

            log.info("filename: {}", fileName);
            response.setHeader("Content-Disposition", "attachment;fileName=" + fileName + ";");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (byteArrayInputStream != null) {
                try {
                    byteArrayInputStream.close();  // 关闭正确的流
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @GetMapping(value = "/image/{type}", produces = MediaType.IMAGE_JPEG_VALUE) // 注意注解的参数，produces = MediaType.IMAGE_JPEG_VALUE
    @SneakyThrows
    public byte[] getImageAll(String imageName, @PathVariable("type") String type) {
        log.info("imageName:{}, type:{}", imageName, type);
        // 图片文件路径
        if (type.equals(SearchTypeEnum.TALK_RECORD.getPath().replaceAll("/", ""))) {
            type += "/result/";
        }
        String imagePath = filesPath + type + "/" + imageName; // √ img标签也支持返回本地磁盘路径和图片的访问方式;
        // 读取图片文件并返回字节数组
        File file = new File(imagePath);
        return Files.readAllBytes(file.toPath());
    }

    @GetMapping(value = "/image/talk/record", produces = MediaType.IMAGE_JPEG_VALUE) // 注意注解的参数，produces = MediaType.IMAGE_JPEG_VALUE
    @SneakyThrows
    public byte[] getTalkRecord(String imageName) {
        // 图片文件路径
        String imagePath = resultPath + imageName; // √ img标签也支持返回本地磁盘路径和图片的访问方式;
        File file = new File(imagePath);
        return Files.readAllBytes(file.toPath());
    }


}
